package com.I9lou.se.lurker.facet.search.support;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.lucene.facet.index.params.DefaultFacetIndexingParams;
import org.apache.lucene.facet.search.FacetsCollector;
import org.apache.lucene.facet.search.params.CountFacetRequest;
import org.apache.lucene.facet.search.params.FacetRequest.SortBy;
import org.apache.lucene.facet.search.params.FacetRequest.SortOrder;
import org.apache.lucene.facet.search.params.FacetSearchParams;
import org.apache.lucene.facet.search.results.FacetResult;
import org.apache.lucene.facet.search.results.FacetResultNode;
import org.apache.lucene.facet.taxonomy.CategoryPath;
import org.apache.lucene.facet.taxonomy.TaxonomyReader;
import org.apache.lucene.index.CorruptIndexException;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.search.IndexSearcher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.I9lou.se.lurker.facet.index.TaxonomyWriterFactory;
import com.I9lou.se.lurker.facet.search.FacetSearchService;
import com.I9lou.se.lurker.remote.SearchCommand;

public class SimpleFacetSearchService implements FacetSearchService {

	private static Logger LOG = LoggerFactory.getLogger(SimpleFacetSearchService.class);
	
	private TaxonomyWriterFactory taxonomyWriterFactory;
	
	public void setTaxonomyWriterFactory(TaxonomyWriterFactory taxonomyWriterFactory) {
		this.taxonomyWriterFactory = taxonomyWriterFactory;
	}

	@Override
	public List<Map<String, Object>> search(int appId, CategoryPath categoryPath,
			int facetResultLimit, SearchCommand searchCommand, IndexSearcher indexSearcher) {
		try {
			FacetSearchParams facetSearchParams = 
					new FacetSearchParams(new DefaultFacetIndexingParams());
			TaxonomyReader taxonomyReader = taxonomyWriterFactory.getTaxonomyReader(appId);
			CountFacetRequest countFacetRequest = new CountFacetRequest(categoryPath, 
																		facetResultLimit);
			countFacetRequest.setNumLabel(facetResultLimit);
			countFacetRequest.setDepth(1);
			countFacetRequest.setSortBy(SortBy.VALUE);
			countFacetRequest.setSortOrder(SortOrder.DESCENDING);
			facetSearchParams.addFacetRequest(countFacetRequest);
			IndexReader indexReader = indexSearcher.getIndexReader();
			FacetsCollector facetsCollector = new FacetsCollector(facetSearchParams, 
																	indexReader, 
																	taxonomyReader);
			LOG.info("[Search-Count]Taxonomy reader size: {}", taxonomyReader.getSize());
			indexSearcher.search(searchCommand.getQuery(), searchCommand.getFilter(), facetsCollector);
			return convertFacetResult(facetsCollector.getFacetResults());
		} catch (CorruptIndexException e) {
			LOG.error("[Search-Count]Corrupt indexReader of LuceneTaxonomyReader! directory: "+taxonomyWriterFactory.getTaxonomyDirectory(appId), e);
			return Collections.emptyList();
		} catch (IOException e) {
			LOG.error("[Search-Count] directory: "+taxonomyWriterFactory.getTaxonomyDirectory(appId), e);
			return Collections.emptyList();
		}
	}
	
	private List<Map<String, Object>> convertFacetResult(List<FacetResult> facetResults) {
		List<Map<String, Object>> results = new ArrayList<Map<String, Object>>();
		if( facetResults!=null && facetResults.size()>0 ){
			FacetResult facetResult = facetResults.get(0);
			Iterator<? extends FacetResultNode> facetResultIterator = facetResult.getFacetResultNode().getSubResults().iterator();
			while( facetResultIterator.hasNext() ){
				FacetResultNode facetResultNode = facetResultIterator.next();
				CategoryPath categoryOfInterest = facetResultNode.getLabel();
				Map<String, Object> result = new HashMap<String, Object>();
				String[] categories = categoryOfInterest.toString(',').split(",");
				result.put("categories", categories);
				result.put("count", Double.valueOf(facetResultNode.getValue()).intValue());
				results.add(result);
			}
		}
		return results;
	}
}
